// MongoDB driver for session manager
// Copyright (C) 2011-2012 Jani Kajala. Licensed under MIT-license.
// Dependencies: Node.js, mongodb (mongodb-native)

var mongo = require( 'mongodb' );
var ObjectID = mongo.ObjectID;

//--------------------------------------------------------------------
// MongoDB session store
//--------------------------------------------------------------------

/** 
 * MongoDB session store. Session DB and collection name is 'sessions'.
 * @param expires Expires in seconds. Default is day (86400).
 */
function SessionStoreMongoDB( expires, host, port ) {
	var self = this;

	if (typeof host == 'undefined') host = 'localhost';
	if (typeof port == 'undefined') port = mongo.Connection.DEFAULT_PORT;
	
	this.expires = (typeof expires == 'undefined' ? 86400 : expires );
	this.dbServer = new mongo.Server( 'localhost', port, {auto_reconnect:true} );
	this.db = new mongo.Db( 'sessions', self.dbServer, {} );
	
	this.db.open( function(err,database) {
		if (err) {console.error( "SessionStoreMongoDB: Connecting to DB failed: %s", err ); return;}
		self.db = database;
		database.collection( 'sessions', function(err,collection) {
			if (err) {console.error( "SessionStoreMongoDB: Failed to get session collection: %s", err ); return;}
			self.sessions = collection;
		} );
	} );
}

/** 
 * Starts new session.
 * @param ses Session doc
 * @param next Callback next(err,sid).
 */
SessionStoreMongoDB.prototype.insert = function( ses, next ) {
	ses._expires = (new Date()).getTime() + this.expires*1000;
	this.sessions.insert( ses, function(err,docs) {
		next( err, docs?docs[0]._id:null );
	} );
};

/** 
 * Set session data.
 * @param sid Session id 
 * @param data Session doc
 * @param next Callback next(err).
 */
SessionStoreMongoDB.prototype.set = function( sid, ses, next ) {
	ses._expires = (new Date()).getTime() + this.expires*1000;
	sid = ( typeof sid==='string' && sid.length == 24 ? new ObjectID(sid) : sid );
	this.sessions.update( {_id:sid}, {$set:ses}, {safe:true}, next );
};

/** 
 * Get session data.
 * @param sid Session id 
 * @param next Callback next(err,ses), where ses is session doc.
 */
SessionStoreMongoDB.prototype.get = function( sid, next ) {
	var self = this;
	sid = ( typeof sid==='string' && sid.length == 24 ? new ObjectID(sid) : sid );
	this.sessions.findOne( {_id:sid}, function(err,doc) {
		if (err) return next(err);
		if ( doc && doc._expires && doc._expires-(new Date()).getTime() > 0 ) {
			next( err, doc );
		}
		else {
			self.sessions.remove( {_id:sid} );
			next( err );
		}
	} );
};

/** 
 * Destroys session data.
 * @param sid Session id 
 * @param next Callback next(err)
 */
SessionStoreMongoDB.prototype.remove = function( sid, next ) {
	sid = ( typeof sid==='string' && sid.length == 24 ? new ObjectID(sid) : sid );
	this.sessions.remove( {_id:sid}, next );
};

//------------------------------------------------------------------------------------------------
// module.exports
//------------------------------------------------------------------------------------------------

module.exports = SessionStoreMongoDB;
